package com.gitee.kenewstar.migration.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.gitee.kenewstar.migration.constants.Const;
import com.gitee.kenewstar.migration.entity.JobCronTriggers;
import com.gitee.kenewstar.migration.entity.JobDetails;
import com.gitee.kenewstar.migration.entity.JobExecutor;
import com.gitee.kenewstar.migration.entity.JobInfo;
import com.gitee.kenewstar.migration.entity.JobTriggers;
import com.gitee.kenewstar.migration.entity.Lov;
import com.gitee.kenewstar.migration.mapper.JobCronTriggersMapper;
import com.gitee.kenewstar.migration.mapper.JobDetailsMapper;
import com.gitee.kenewstar.migration.mapper.JobExecutorMapper;
import com.gitee.kenewstar.migration.mapper.JobInfoMapper;
import com.gitee.kenewstar.migration.mapper.JobTriggersMapper;
import com.gitee.kenewstar.migration.service.JobService;
import com.gitee.kenewstar.migration.util.Util;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author kenewstar
 */
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class JobServiceImpl implements JobService {

    public static final String TRIGGER_NAME = "TRIGGER_NAME";
    public static final String TRIGGER_GROUP = "TRIGGER_GROUP";

    private final JobInfoMapper jobInfoMapper;
    private final JobDetailsMapper jobDetailsMapper;
    private final JobTriggersMapper jobTriggersMapper;
    private final JobCronTriggersMapper jobCronTriggersMapper;
    private final JobExecutorMapper jobExecutorMapper;

    @Override
    @DS(Const.DEV)
    public List<JobExecutor> devSelectExecutor(List<Long> executorIds) {
        QueryWrapper<JobExecutor> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("executor_id", executorIds);
        return this.jobExecutorMapper.selectList(queryWrapper);
    }

    @Override
    @DS(Const.DEV)
    public List<JobInfo> devSelectJobInfo(List<String> jobCodeList, Long tenantId) {
        if (CollUtil.isEmpty(jobCodeList)) {
            return Collections.emptyList();
        }
        QueryWrapper<JobInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("job_code", jobCodeList);
        if (Objects.nonNull(tenantId)) {
            queryWrapper.in(Const.TENANT_ID, tenantId);
        }
        return this.jobInfoMapper.selectList(queryWrapper);
    }

    @Override
    @DS(Const.DEV)
    public List<JobInfo> devSelectJobInfoList(List<JobInfo> list) {
        if (CollUtil.isEmpty(list)) {
            return Collections.emptyList();
        }
        Map<String, String> filterMap = list.stream().collect(Collectors.toMap(x -> x.getJobCode() + "-" + x.getTenantId(), JobInfo::getJobCode));
        QueryWrapper<JobInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("job_code", list.stream().map(JobInfo::getJobCode).collect(Collectors.toSet()));
        queryWrapper.in(Const.TENANT_ID, list.stream().map(JobInfo::getTenantId).collect(Collectors.toSet()));
        List<JobInfo> lovList = this.jobInfoMapper.selectList(queryWrapper);
        return lovList.stream().filter(x -> Objects.nonNull(filterMap.get(x.getJobCode() + "-" + x.getTenantId()))).collect(Collectors.toList());
    }

    @Override
    @DS(Const.DEV)
    public List<JobTriggers> devSelectJobTriggers(List<Long> jobIds, List<Long> tenantIds) {
        QueryWrapper<JobTriggers> queryWrapper = new QueryWrapper<>();
        queryWrapper.in(TRIGGER_NAME, jobIds);
        queryWrapper.in(TRIGGER_GROUP, tenantIds);
        return this.jobTriggersMapper.selectList(queryWrapper);
    }

    @Override
    @DS(Const.DEV)
    public List<JobCronTriggers> devSelectJobCronTriggers(List<Long> jobIds, List<Long> tenantIds) {
        QueryWrapper<JobCronTriggers> queryWrapper = new QueryWrapper<>();
        queryWrapper.in(TRIGGER_NAME, jobIds);
        queryWrapper.in(TRIGGER_GROUP, tenantIds);
        return this.jobCronTriggersMapper.selectList(queryWrapper);
    }

    @Override
    @DS(Const.DEV)
    public List<JobDetails> devSelectJobDetails(List<Long> jobIds, List<Long> tenantIds) {
        QueryWrapper<JobDetails> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("JOB_NAME", jobIds);
        queryWrapper.in("JOB_GROUP", tenantIds);
        return this.jobDetailsMapper.selectList(queryWrapper);
    }

    @Override
    @DS(Const.UAT)
    public List<JobExecutor> uatSelectExecutor(List<String> executorCodeList) {
        QueryWrapper<JobExecutor> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("executor_code", executorCodeList);
        return this.jobExecutorMapper.selectList(queryWrapper);
    }

    @Override
    @DS(Const.UAT)
    @Transactional(rollbackFor = Exception.class)
    public void uatInsertJobInfo(List<JobInfo> list) {
        list.forEach(v -> v.setTenantId(Util.getTenant(v.getTenantId())));
        list.forEach(this.jobInfoMapper::insert);
    }

    @Override
    @DS(Const.UAT)
    @Transactional(rollbackFor = Exception.class)
    public void uatInsertTriggers(List<JobTriggers> list) {
        list.forEach(v -> v.setTenantId(Util.getTenant(v.getTenantId())));
        list.forEach(v -> v.setJobGroup(Util.getTenant(v.getJobGroup())));
        list.forEach(this.jobTriggersMapper::insert);
    }

    @Override
    @DS(Const.UAT)
    @Transactional(rollbackFor = Exception.class)
    public void uatInsertCronTriggers(List<JobCronTriggers> list) {
        list.forEach(v -> v.setTenantId(Util.getTenant(v.getTenantId())));
        list.forEach(this.jobCronTriggersMapper::insert);
    }

    @Override
    @DS(Const.UAT)
    @Transactional(rollbackFor = Exception.class)
    public void uatInsertJobDetails(List<JobDetails> list) {
        list.forEach(v -> v.setTenantId(Util.getTenant(v.getTenantId())));
        list.forEach(this.jobDetailsMapper::insert);
    }
}
